/**
 * $Revision$
 * $Date$
 *
 * Copyright (C) https://gitee.com/baibaiclouds/platform baibai. All rights reserved.
 * <p>
 * This software is the confidential and proprietary information of baibai.
 * You shall not disclose such Confidential Information and shall use it only
 * in accordance with the terms of the agreements you entered into with baibai.
 * 
 * Modified history:
 *   baibai  2020年2月8日 下午8:38:37  created
 */
package com.desktop.web.service.role;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.desktop.web.core.exception.BusinessException;
import com.desktop.web.service.config.ConfigService;
import com.desktop.web.service.log.LogService;
import com.desktop.web.service.node.NodeService;
import com.desktop.web.service.user.UserService;
import com.desktop.web.uda.entity.Node;
import com.desktop.web.uda.entity.Right;
import com.desktop.web.uda.entity.Role;
import com.desktop.web.uda.entity.RoleNode;
import com.desktop.web.uda.entity.RoleRight;
import com.desktop.web.uda.entity.RoleUser;
import com.desktop.web.uda.entity.User;
import com.desktop.web.uda.mapper.RightMapper;
import com.desktop.web.uda.mapper.RoleMapper;
import com.desktop.web.uda.mapper.RoleNodeMapper;
import com.desktop.web.uda.mapper.RoleRightMapper;
import com.desktop.web.uda.mapper.RoleUserMapper;

/**
 * 
 *
 * @author baibai
 */
@Service
public class RoleService {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private LogService logService;

    @Autowired
    private RightMapper rightMapper;

    @Autowired
    private RoleMapper roleMapper;

    @Autowired
    private RoleUserMapper roleUserMapper;

    @Autowired
    private RoleNodeMapper roleNodeMapper;

    @Autowired
    private RoleRightMapper roleRightMapper;

    @Autowired
    private UserService userService;

    @Autowired
    private ConfigService configService;

    @Autowired
    private NodeService nodeService;

    /**
     * 添加角色
     * 
     * @param title
     * @return
     */
    public Role addRole(String title) {
        Role role = getRoleByTitle(title);
        if (role != null) {
            throw new BusinessException(title + " 角色名称已存在，无法添加");
        }

        role = new Role();
        role.setTitle(title);

        roleMapper.insert(role);
        logService.addLogCuruser("角色管理", "添加角色成功，角色名称:{}", title);
        return role;
    }

    /**
     * 根据角色名称获取角色详细信息
     * 
     * @param title
     * @return
     */
    public Role getRoleByTitle(String title) {
        Role entity = new Role();
        entity.setTitle(title);
        QueryWrapper<Role> queryWrapper = new QueryWrapper<Role>();
        queryWrapper.setEntity(entity);
        return roleMapper.selectOne(queryWrapper);
    }

    /**
     * 判断是超级管理员
     * 
     * @param uid
     * @return
     */
    public boolean isAdminByUid(Long uid) {
        List<Role> roles = this.getRoleListByUid(uid);
        if (roles == null || roles.isEmpty()) {
            return false;
        }

        for (Role item : roles) {
            if (item.getId().equals(UserService.ADMIN_ROLE_ID)) {
                return true;
            }
        }

        return false;
    }

    /**
     * 根据用户id获取角色列表
     * 
     * @param uid
     * @return
     */
    public List<Role> getRoleListByUid(Long uid) {

        RoleUser entity = new RoleUser();
        entity.setUserId(uid);
        QueryWrapper<RoleUser> queryWrapper = new QueryWrapper<RoleUser>();
        queryWrapper.setEntity(entity);
        List<RoleUser> roleUserList = roleUserMapper.selectList(queryWrapper);
        List<Long> ids = new ArrayList<Long>();

        if (roleUserList == null || roleUserList.isEmpty()) {
            return new ArrayList<Role>();
        }

        roleUserList.forEach((item) -> {
            ids.add(item.getRoleId());
        });

        return roleMapper.selectBatchIds(ids);
    }

    /**
     * 删除用户对于的角色
     * 
     * @param uid
     */
    public void deleteRoleUser(Long uid) {
        RoleUser entity = new RoleUser();
        entity.setUserId(uid);
        QueryWrapper<RoleUser> queryWrapper = new QueryWrapper<RoleUser>();
        queryWrapper.setEntity(entity);
        roleUserMapper.delete(queryWrapper);
    }

    /**
     * 更新角色信息
     * 
     * @param role
     */
    public void updateRole(Role role) {

        Role tempRole = getRoleByTitle(role.getTitle());
        if (tempRole != null && !tempRole.getId().equals(role.getId())) {
            throw new BusinessException(role.getTitle() + " 角色名称已存在，无法修改");
        }

        roleMapper.updateById(role);
        logService.addLogCuruser("角色管理", "编辑角色成功，角色名称:{},id:{}", role.getTitle(), role.getId());
    }

    /**
     * 获取角色列表
     * 
     * @return
     */
    public List<Role> getRoleList() {
        QueryWrapper<Role> queryWrapper = new QueryWrapper<Role>();
        queryWrapper.orderByDesc("id");
        return roleMapper.selectList(queryWrapper);
    }

    /**
     * 删除角色
     * 
     * @param roleId
     */
    public void deleteRole(Long roleId) {

        if (UserService.ADMIN_ROLE_ID.equals(roleId)) {
            throw new BusinessException("此角色无法删除");
        }

        Role role = roleMapper.selectById(roleId);
        if (role == null) {
            throw new BusinessException("roleid非法");
        }

        RoleUser entityRoleUser = new RoleUser();
        entityRoleUser.setRoleId(roleId);
        QueryWrapper<RoleUser> queryWrapperRoleUser = new QueryWrapper<RoleUser>();
        queryWrapperRoleUser.setEntity(entityRoleUser);
        roleUserMapper.delete(queryWrapperRoleUser);

        RoleRight entityRoleRight = new RoleRight();
        entityRoleRight.setRoleId(roleId);
        QueryWrapper<RoleRight> queryWrapperRoleRight = new QueryWrapper<RoleRight>();
        queryWrapperRoleRight.setEntity(entityRoleRight);
        roleRightMapper.delete(queryWrapperRoleRight);

        roleMapper.deleteById(roleId);
        logService.addLogCuruser("角色管理", "删除角色成功，角色名称:{},id:{}", role.getTitle(), role.getId());
    }

    /**
     * 根据target获取权限信息
     * 
     * @param target
     * @return
     */
    public Right getRightByTarget(String target) {
        Right entityRoleRight = new Right();
        entityRoleRight.setTarget(target);
        QueryWrapper<Right> queryWrapperRight = new QueryWrapper<Right>();
        queryWrapperRight.setEntity(entityRoleRight);
        return rightMapper.selectOne(queryWrapperRight);
    }

    /**
     * 更新角色权限
     * 
     * @param roleId
     * @param rights
     */
    public void updateRightRole(Long roleId, Map<String, Object> rights) {
        Role role = roleMapper.selectById(roleId);
        if (role == null) {
            throw new BusinessException("roleId非法");
        }

        RoleRight entityRoleRight = new RoleRight();
        entityRoleRight.setRoleId(roleId);
        QueryWrapper<RoleRight> queryWrapperRoleRight = new QueryWrapper<RoleRight>();
        queryWrapperRoleRight.setEntity(entityRoleRight);
        roleRightMapper.delete(queryWrapperRoleRight);

        List<Right> addRights = new ArrayList<Right>();
        for (String key : rights.keySet()) {
            boolean flag = (Boolean) rights.get(key);
            if (!flag) {
                continue;
            }
            Right tempRight = getRightByTarget(key);
            if (tempRight == null) {
                continue;
            }
            addRights.add(tempRight);
        }

        addRights.forEach((right) -> {
            RoleRight tempAddRoleRight = new RoleRight();
            tempAddRoleRight.setRoleId(roleId);
            tempAddRoleRight.setRightId(right.getId());
            tempAddRoleRight.setRightTarget(right.getTarget());
            roleRightMapper.insert(tempAddRoleRight);
        });

        logService.addLogCuruser("角色管理", "修改角色，角色名称:{},id:{},rights:{}", role.getTitle(), role.getId(), addRights);
    }

    /**
     * 根据角色id获取权限列表
     * 
     * @param roleId
     * @return
     */
    public List<String> getRightTargetListByRoleid(Long roleId) {
        List<RoleRight> roleRightList = this.getRoleRightListByRoleid(roleId);

        List<String> targets = new ArrayList<String>();
        roleRightList.forEach((item) -> {
            targets.add(item.getRightTarget());
        });
        return targets;
    }

    /**
     * 获取根据uid获取权限目标列表
     * 
     * @param uid
     * @return
     */
    public List<String> getRightTargetListByUid(Long uid) {
        List<String> retList = new ArrayList<String>();

        if (this.isAdminByUid(uid)) {
            List<Right> rights = rightMapper.selectList(null);
            for (Right item : rights) {
                retList.add(item.getTarget());
            }

            return retList;
        }

        Set<String> listSet = new HashSet<>();
        List<Role> roles = this.getRoleListByUid(uid);
        if (roles == null || roles.isEmpty()) {
            return new ArrayList<String>();
        }

        for (Role item : roles) {
            List<String> targetList = this.getRightTargetListByRoleid(item.getId());
            for (String target : targetList) {
                listSet.add(target);
            }
        }

        listSet.forEach((item) -> {
            retList.add(item);
        });

        return retList;
    }

    /**
     * 根据角色id获取权限列表
     * 
     * @param roleId
     * @return
     */
    public List<RoleRight> getRoleRightListByRoleid(Long roleId) {
        RoleRight tempAddRoleRight = new RoleRight();
        tempAddRoleRight.setRoleId(roleId);

        QueryWrapper<RoleRight> queryWrapper = new QueryWrapper<RoleRight>();
        queryWrapper.setEntity(tempAddRoleRight);
        return roleRightMapper.selectList(queryWrapper);
    }

    /**
     * 根据角色id获取用户列表
     * 
     * @param roleId
     * @return
     */
    public List<RoleUser> getRoleUserListByRoleid(Long roleId) {
        RoleUser entity = new RoleUser();
        entity.setRoleId(roleId);

        QueryWrapper<RoleUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.setEntity(entity);
        return roleUserMapper.selectList(queryWrapper);
    }

    /**
     * 根据角色id获取设备节点列表
     * 
     * @param roleId
     * @return
     */
    public List<RoleNode> getRoleNodeListByRoleid(Long roleId) {
        RoleNode entity = new RoleNode();
        entity.setRoleId(roleId);
        QueryWrapper<RoleNode> queryWrapper = new QueryWrapper<>();
        queryWrapper.setEntity(entity);
        return roleNodeMapper.selectList(queryWrapper);
    }

    /**
     * 根据角色id获取用户列表
     * 
     * @param roleId
     * @return
     */
    public List<User> getRoleUserList(Long roleId) {
        List<RoleUser> roleRightList = this.getRoleUserListByRoleid(roleId);
        List<User> users = new ArrayList<User>();
        roleRightList.forEach((item) -> {
            User user = userService.getUserById(item.getUserId());
            if (user == null) {
                return;
            }
            users.add(user);
        });
        return users;
    }

    /**
     * 添加角色用户
     * 
     * @param roleId
     * @param uids
     * @return
     */
    public void addRoleUserList(Long roleId, List<Long> uids) {

        Role role = roleMapper.selectById(roleId);
        if (role == null) {
            throw new BusinessException("参数错误");
        }

        for (Long uid : uids) {

            User user = userService.getUserById(uid);
            if (user == null) {
                continue;
            }

            try {
                RoleUser roleUser = new RoleUser();
                roleUser.setRoleId(roleId);
                roleUser.setUserId(uid);
                roleUserMapper.insert(roleUser);
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
            }
        }

        logService.addLogCuruser("角色管理", "添加角色用户成功，角色名称:{},uids:{}", role.getTitle(), uids);
    }

    /**
     * 删除用户角色
     * 
     * @param roleId
     * @param uid
     */
    public void delRoleUser(Long roleId, Long uid) {

        if (roleId.equals(UserService.ADMIN_ROLE_ID) && uid.equals(configService.getAdminRootUID())) {
            throw new BusinessException("默认的超级管理员无法删除");
        }

        Role role = roleMapper.selectById(roleId);
        User user = userService.getUserById(uid);

        if (role == null || user == null) {
            throw new BusinessException("参数错误");
        }

        RoleUser roleUser = new RoleUser();
        roleUser.setRoleId(roleId);
        roleUser.setUserId(uid);

        QueryWrapper<RoleUser> queryWrapper = new QueryWrapper<RoleUser>();
        queryWrapper.setEntity(roleUser);
        roleUserMapper.delete(queryWrapper);

        logService.addLogCuruser("角色管理", "删除角色用户成功，角色名称:{},用户名称:{}", role.getTitle(), user.getUsername());
    }

    /**
     * 获取角色设备节点列表
     * 
     * @param roleId
     * @return
     */
    public List<Node> getRoleNodeList(Long roleId) {
        List<RoleNode> roleRightList = this.getRoleNodeListByRoleid(roleId);
        List<Node> users = new ArrayList<>();
        roleRightList.forEach((item) -> {
            Node node = nodeService.getNodeById(item.getNodeId());
            if (node == null) {
                return;
            }
            users.add(node);
        });
        return users;
    }

    /**
     * 更新角色对应的节点
     * 
     * @param roleId
     * @param ids
     */
    public void updateRoleNodeList(Long roleId, List<Long> ids) {

        Role role = roleMapper.selectById(roleId);
        if (role == null) {
            throw new BusinessException("参数错误");
        }

        RoleNode entity = new RoleNode();
        entity.setRoleId(roleId);
        QueryWrapper<RoleNode> queryWrapper = new QueryWrapper<>();
        queryWrapper.setEntity(entity);
        roleNodeMapper.delete(queryWrapper);

        ids.forEach((item) -> {
            RoleNode tempEntity = new RoleNode();
            tempEntity.setRoleId(roleId);
            tempEntity.setNodeId(item);
            roleNodeMapper.insert(tempEntity);
        });

        logService.addLogCuruser("角色管理", "更新角色节点成功，角色名称:{},节点IDS:{}", role.getTitle(), ids);
    }

    /**
     * 删除角色对于的节点
     * 
     * @param roleId
     * @param nodeId
     */
    public void delRoleNode(Long roleId, Long nodeId) {

        Role role = roleMapper.selectById(roleId);
        if (role == null) {
            throw new BusinessException("参数错误");
        }

        Node node = nodeService.getNodeById(nodeId);
        if (node == null) {
            throw new BusinessException("参数错误");
        }

        RoleNode entity = new RoleNode();
        entity.setRoleId(roleId);
        entity.setNodeId(nodeId);
        QueryWrapper<RoleNode> queryWrapper = new QueryWrapper<>();
        queryWrapper.setEntity(entity);
        roleNodeMapper.delete(queryWrapper);

        logService.addLogCuruser("角色管理", "删除角色节点成功，角色名称:{},节点名称:{}", role.getTitle(), node.getTitle());
    }

    /**
     * 判断是否有权限
     * 
     * @param user
     * @param rightstr
     * @return
     */
    public boolean hasRight(User user, String rightstr) {

        List<Role> roles = this.getRoleListByUid(user.getId());
        if (roles == null || roles.isEmpty()) {
            return false;
        }

        RoleRight roleRight = new RoleRight();
        QueryWrapper<RoleRight> queryWrapper = new QueryWrapper<RoleRight>();
        queryWrapper.setEntity(roleRight);

        String[] rights = rightstr.split(",");
        for (String right : rights) {
            for (Role item : roles) {
                roleRight.setRoleId(item.getId());
                roleRight.setRightTarget(right);
                if (roleRightMapper.selectCount(queryWrapper) > 0) {
                    return true;
                }
            }
        }

        return false;
    }

}
